# app/services/dish_service.py
import base64

from app.models import Dish, Image, DishImage, MerchantInfo, Category
from django.db import transaction
from django.core.exceptions import ValidationError
from middleware.util import make_response, decode_base64_image


class DishService:
    @staticmethod
    def upload_dish(
        merchant_id,
        dish_name,
        price,
        category_id,
        customization_options=None,
        stock=0,
        status='on_shelf',
        images=None  # List of dicts: { "data": "base64", "mime_type": "image/png" }
    ):
        try:
            merchant = MerchantInfo.objects.get(merchant_id=merchant_id)
        except MerchantInfo.DoesNotExist:
            return make_response(code=404, message="商家不存在")

        if not dish_name or price is None or not category_id:
            return make_response(code=400, message="菜品名称、价格和分类是必填项")

        try:
            category = Category.objects.get(category_id=category_id, merchant=merchant)
        except Category.DoesNotExist:
            return make_response(code=404, message="分类不存在或不属于该商家")

        with transaction.atomic():
            # 1. 创建菜品
            dish = Dish.objects.create(
                merchant=merchant,
                category=category,
                dish_name=dish_name,
                price=price,
                customization_options=customization_options,
                stock=stock,
                status=status
            )

            # 2. 处理图片上传
            dish_images = []
            for idx, image_info in enumerate(images or []):
                image_data = image_info.get("data")
                mime_type = image_info.get("mime_type")

                image_binary = decode_base64_image(image_data, mime_type)

                image = Image.objects.create(
                    image_data=image_binary,
                    mime_type=mime_type
                )
                DishImage.objects.create(
                    dish=dish,
                    image=image,
                    sort_order=idx
                )
                dish_images.append(str(image.image_id))

        return make_response(
            code=201,
            message="菜品上传成功",
            data={
                "dish_id": str(dish.dish_id),
                "dish_name": dish.dish_name,
                "price": float(dish.price),
                "stock": dish.stock,
                "status": dish.status,
                "category_id": str(category.category_id),
                "image_ids": dish_images
            }
        )

    @staticmethod
    def update_dish(
            dish_id,
            merchant_id,
            dish_name=None,
            price=None,
            category_id=None,
            customization_options=None,
            stock=None,
            status=None,
            images=None  # List of { "data": "...", "mime_type": "..." }
    ):
        try:
            dish = Dish.objects.get(dish_id=dish_id, merchant_id=merchant_id)
        except Dish.DoesNotExist:
            return make_response(code=404, message="菜品不存在或不属于该商家")

        if category_id:
            try:
                category = Category.objects.get(category_id=category_id, merchant_id=merchant_id)
                dish.category = category
            except Category.DoesNotExist:
                return make_response(code=404, message="分类不存在或不属于该商家")

        with transaction.atomic():
            # 1. 更新菜品基本信息
            if dish_name is not None:
                dish.dish_name = dish_name
            if price is not None:
                dish.price = price
            if customization_options is not None:
                dish.customization_options = customization_options
            if stock is not None:
                dish.stock = stock
            if status is not None:
                dish.status = status
            dish.save()

            # 2. 如果有新图片，先删除原有图再新增
            if images is not None:
                # 删除原有图片（可选）：如果要保留历史图片，可改为软删除
                # DishImage.objects.filter(dish=dish).delete()

                for idx, image_info in enumerate(images or []):
                    image_data = image_info.get("data")
                    mime_type = image_info.get("mime_type")

                    image_binary = decode_base64_image(image_data, mime_type)

                    image = Image.objects.create(
                        image_data=image_binary,
                        mime_type=mime_type
                    )
                    DishImage.objects.create(
                        dish=dish,
                        image=image,
                        sort_order=idx
                    )

        return make_response(
            code=200,
            message="菜品信息更新成功",
            data={
                "dish_id": str(dish.dish_id),
                "dish_name": dish.dish_name,
                "price": float(dish.price),
                "stock": dish.stock,
                "status": dish.status,
                "image_count": dish.images.count()
            }
        )

    @staticmethod
    def update_dish_stock(dish_id, merchant_id, new_stock):
        """
        更新菜品库存，并自动判断是否下架
        :param dish_id: 菜品 ID
        :param merchant_id: 商家 ID
        :param new_stock: 新库存值（必须 >= 0）
        :return: 统一格式响应
        """
        try:
            dish = Dish.objects.get(dish_id=dish_id, merchant_id=merchant_id)
        except Dish.DoesNotExist:
            return make_response(code=404, message="菜品不存在或不属于该商家")

        if not isinstance(new_stock, int) or new_stock < 0:
            return make_response(code=400, message="库存必须为非负整数")

        dish.stock = new_stock
        dish.save()  # save() 会自动触发状态变更逻辑（stock=0 → 下架）

        return make_response(
            code=200,
            message="库存更新成功",
            data={
                "dish_id": str(dish.dish_id),
                "dish_name": dish.dish_name,
                "stock": dish.stock,
                "status": dish.status
            }
        )

    @staticmethod
    def list_categories_with_dishes(merchant_id):
        """
        获取商家的所有分类及其菜品（仅返回 ID 和名称，按排序顺序）
        :param merchant_id: 商家 UUID
        :return: 统一格式响应
        """
        try:
            merchant = MerchantInfo.objects.get(merchant_id=merchant_id)
        except MerchantInfo.DoesNotExist:
            return make_response(code=404, message="商家不存在")

        categories = Category.objects.filter(merchant=merchant).order_by('sort_order')
        result = []

        for category in categories:
            dishes = Dish.objects.filter(category=category, merchant=merchant).order_by('sort_order')
            dish_list = [
                {
                    "dish_id": str(dish.dish_id),
                    "dish_name": dish.dish_name,
                    "sort_order":dish.sort_order,
                }
                for dish in dishes
            ]

            result.append({
                "category_id": str(category.category_id),
                "category_name": category.category_name,
                "dishes": dish_list,
                "sort_order":category.sort_order,
            })

        return make_response(
            code=200,
            message="获取成功",
            data=result
        )

    @staticmethod
    def get_dish_detail(dish_id, merchant_id):
        """
        获取菜品详细信息 + 所有图片数据（返回 Base64）
        :param dish_id: 菜品 ID
        :param merchant_id: 商家 ID（确保权限）
        :return: 统一格式响应
        """
        try:
            dish = Dish.objects.get(dish_id=dish_id, merchant_id=merchant_id)
        except Dish.DoesNotExist:
            return make_response(code=404, message="菜品不存在或不属于当前商家")

        # 获取图片数据
        images = []
        for di in dish.images.select_related('image').order_by('sort_order'):
            image_binary = di.image.image_data  # bytes 类型
            base64_data = base64.b64encode(image_binary).decode('utf-8')  # Base64 字符串

            images.append({
                "data": base64_data,
                "mime_type": di.image.mime_type
            })

        return make_response(
            code=200,
            message="成功",
            data={
                "dish_id": str(dish.dish_id),
                "dish_name": dish.dish_name,
                "price": float(dish.price),
                "stock": dish.stock,
                "status": dish.status,
                "customization_options": dish.customization_options,
                "images": images
            }
        )